﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Globalization;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.XPath;

namespace Sinacor.Infra.Core.Licensing
{
	[Serializable]
    public class Licensing
    {
		DateTime? _goodThru;
		int? _id;
		int? _aliasId;
		Active? _active;
		Description _description;
		DateTime? _created;
		string _LegalRegistrationID;
		string _aliasName;
		List<Company> _companies;
		int _moduleId;
		int _companyId;
		List<Module> _modules;
		Treaty? _treaty;
		List<LicensingCompanyModule> _licensingCompanyModule;

        public Licensing()
        {
            Created = DateTime.Now;
            _companies = new List<Company>();
            _description = new Description();

            _licensingCompanyModule = new List<LicensingCompanyModule>();
            _modules = new List<Module>();
            _treaty = new Treaty();
            _goodThru = DateTime.Now;
        }
        
        [DataMember]
        public DateTime? GoodThru
        {
            get { return _goodThru; }
            set { _goodThru = value; }
        }
        
        public int? Id
        {
            get { return _id; }
            set { _id = value; }
        }
		
		public int? AliasId
		{
			get { return _aliasId; }
			set { _aliasId = value; }
		}
        
        public Active? Active
        {
            get { return _active; }
            set { _active = value; }
        }
        
        public Description Description
        {
            get { return _description; }
            set { _description = value; }
        }

        public DateTime? Created
        {
            get { return _created; }
            set { _created = value; }
        }
        
        public string OwnerLegalRegistrationId
        {
            get { return _LegalRegistrationID; }
            set { _LegalRegistrationID = value; }
        }

		public string AliasName
		{
			get { return _aliasName; }
			set { _aliasName = value; }
		}

        public List<Company> Companies
        {
            get { return _companies; }
            set { _companies = value; }
        }

        public int ModuleId
        {
            get { return _moduleId; }
            set { _moduleId = value; }
        }

        public int CompanyId
        {
            get { return _companyId; }
            set { _companyId = value; }
        }

        public List<Module> Modules
        {
            get { return _modules; }
            set { _modules = value; }
        }

        public Treaty? Treaty
        {
            get { return _treaty; }
            set { _treaty = value; }
        }

        public List<LicensingCompanyModule> LicensingCompanyModule
        {
            get { return _licensingCompanyModule; }
            set { _licensingCompanyModule = value; }
        }

        public string CheckSum
        {
            get
            {
                return string.Empty;
            }
        }

        public static string Serialize(Licensing licensing)
        {
            StringBuilder cpyNodes = new StringBuilder();
            string licNode = SerializationTemplate.LicensingNodeTemplate;
            string modNode = SerializationTemplate.ModuleNodeTemplate;
            string cpyNode = SerializationTemplate.CompanyNodeTemplate;
            int indexModule = 1;

            licNode = licNode.Replace("<[@create@]>", licensing.Created.Value.ToString("yyyy-MM-dd HH:mm:ss"));
            licNode = licNode.Replace("<[@goodthru@]>", licensing.GoodThru.Value.ToString("yyyy-MM-dd HH:mm:ss"));
            licNode = licNode.Replace("<[@licensingid@]>", licensing.Id.ToString());
            licNode = licNode.Replace("<[@AliasName@]>", licensing.AliasName);
            licNode = licNode.Replace("<[@descriptionid@]>", licensing.Description.Id.ToString());
            licNode = licNode.Replace("<[@ownerLegalregistrationid@]>", licensing.OwnerLegalRegistrationId);
            licNode = licNode.Replace("<[@treaty@]>", TreatyConverter.ConvertTreatyToInt(licensing.Treaty.Value).ToString());

            string companies = String.Empty;
            string modules = String.Empty;
            foreach (Company company in licensing.Companies)
            {
                if (!string.IsNullOrEmpty(company.Name))
                {
                    companies = companies + cpyNode;
                    companies = companies.Replace("<[@companyname@]>", company.Name);
                    companies = companies.Replace("<[@companyid@]>", company.CompanyId.ToString());
                    companies = companies.Replace("<[@companylegalregistrationid@]>", company.LegalRegistrationId);
                    companies = companies.Replace("<[@sinacorcompanyid@]>", company.SinacorCompanyId.ToString());

                    cpyNodes.Append("\r\n\t" + companies);
                    modules = String.Empty;
                    foreach (Module module in company.Modules)
                    {
                        modules = modules + modNode;
                        modules = modules.Replace("<[@idmodule@]>", module.ID.ToString());
                        modules = modules.Replace("<[@modulename@]>", module.Name);
                        modules = modules.Replace("<[@modulemonogram@]>", module.Monogram);
                        modules = modules.Replace("<[@moduleplus@]>", module.Plus.ToString(CultureInfo.GetCultureInfo("en-us")));
                        modules = modules.Replace("<[@goodthru@]>", module.GoodThru.ToString("yyyy-MM-dd HH:mm:ss"));

                        if (indexModule > 1)
                            cpyNodes.Append("\r\n\t\t" + modules);
                        else
                            cpyNodes.Append(modules);

                        modules = String.Empty;
                        indexModule += 1;
                    }
                    indexModule = 1;
                    companies = String.Empty;
                    cpyNodes.Append("\r\n\t</Company>");
                }
            }

            if (cpyNodes.Length == 0)
                licNode = licNode.Replace("<[@companies@]>", string.Empty);
            else
               licNode = licNode.Replace("<[@companies@]>", cpyNodes.ToString());

            return licNode;
        }

        public static Licensing UnSerialize(byte[] _dencryptedLicensing)
        {
            Licensing licensing = new Licensing();
            XmlDocument doc = new XmlDocument();

            using(MemoryStream ms = new MemoryStream(_dencryptedLicensing))
            {
                doc.Load(ms);
            }

            if (!string.IsNullOrEmpty(doc.DocumentElement.Attributes["LicensingId"].Value))
                licensing.Id = Convert.ToInt32(doc.DocumentElement.Attributes["LicensingId"].Value);
            
            licensing.Created = DateTime.ParseExact(doc.DocumentElement.Attributes["Create"].Value, "yyyy-MM-dd HH:mm:ss", CultureInfo.CurrentCulture);

            if (doc.DocumentElement.Attributes["AliasName"] != null)
                licensing.AliasName = doc.DocumentElement.Attributes["AliasName"].Value;

            if (doc.DocumentElement.Attributes["GoodThru"] != null)
                licensing.GoodThru = DateTime.ParseExact(doc.DocumentElement.Attributes["GoodThru"].Value, "yyyy-MM-dd HH:mm:ss", CultureInfo.CurrentCulture);

            if (!string.IsNullOrEmpty(doc.DocumentElement.Attributes["DescriptionId"].Value))
                licensing.Description.Id = Convert.ToInt32(doc.DocumentElement.Attributes["DescriptionId"].Value);

            licensing.Description.TypeDescription = Sinacor.Infra.Core.Licensing.TypeDescription.Alterar;  
            licensing.Active = Sinacor.Infra.Core.Licensing.Active.Ativo;

            licensing.OwnerLegalRegistrationId = doc.DocumentElement.Attributes["OwnerLegalRegistrationId"].Value;

            licensing.Treaty = TreatyConverter.ConvertIntToTreaty(Int32.Parse(doc.DocumentElement.Attributes["Treaty"].Value));
            
            licensing.Companies = CreateCompaniesCollection(doc);
                        
            return licensing;
        }

        static string FindExpressionContent(string dencryptedLicensing, string fieldname)
        {
            string result;

            int idxIniExpr = dencryptedLicensing.IndexOf(fieldname + "=\"") + fieldname.Length + 2;
            int idxEndExpr = dencryptedLicensing.IndexOf("\"", idxIniExpr + 1);

            result = dencryptedLicensing.Substring(idxIniExpr, idxEndExpr - idxIniExpr);
            
            return result;
        }

        static List<Module> CreateModulesCollection(XmlNode nodeCompany)
        {
            List<Module> result = new List<Module>();

            foreach (XmlNode node in nodeCompany.ChildNodes)
            {
                Module module = new Module();
                module.ID = Int32.Parse(node.Attributes["IdModule"].Value);
                module.Name = node.Attributes["Name"].Value;
                module.Monogram = node.Attributes["Monogram"].Value;
                module.Plus = Boolean.Parse(node.Attributes["Plus"].Value);
                module.GoodThru = DateTime.ParseExact(node.Attributes["GoodThru"].Value, "yyyy-MM-dd HH:mm:ss", CultureInfo.CurrentCulture);
                result.Add(module);
            }

            return result;
        }

        static List<Company> CreateCompaniesCollection(XmlDocument doc)
        {
            List<Company> result = new List<Company>();

            foreach (XmlNode node in doc.SelectNodes("//Company"))
            {
                Company company = new Company();
                company.CompanyId = Int32.Parse(node.Attributes["CompanyID"].Value);
                company.Name = node.Attributes["Name"].Value;
                company.LegalRegistrationId = node.Attributes["LegalRegistrationId"].Value;
                company.SinacorCompanyId = Int32.Parse(node.Attributes["SinacorCompanyId"].Value);
                company.Modules = CreateModulesCollection(node);
                result.Add(company);
            }

            return result;
        }

        public object Clone()
        {
            return (Licensing) MemberwiseClone();
        }
    }
}